set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_SYSTEM_VERSION 1)
cmake_minimum_required(VERSION 3.22)

# specify cross-compilers and tools
set(STM32 1)
# set(AT32 1)
if(DEFINED STM32)
set(ARM 1)
add_definitions(-DSTM32)
elseif(DEFINED AT32)
add_definitions(-DAT32)
set(ARM 1)
else()
add_definitions(-DCH32)
set(RISCV 1)
endif()

if(DEFINED ARM)
set(CMAKE_C_COMPILER "arm-none-eabi-gcc")
set(CMAKE_CXX_COMPILER "arm-none-eabi-g++")
set(CMAKE_ASM_COMPILER  "arm-none-eabi-gcc")
set(CMAKE_AR "arm-none-eabi-ar")
set(CMAKE_OBJCOPY "arm-none-eabi-objcopy")
set(CMAKE_OBJDUMP "arm-none-eabi-objdump")
set(SIZE "arm-none-eabi-size")
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)

add_compile_options(-mfloat-abi=hard -mfpu=fpv4-sp-d16)
add_link_options(-mfloat-abi=hard -mfpu=fpv4-sp-d16)
add_compile_options(-mcpu=cortex-m4 -mthumb)
add_compile_options(-ffunction-sections -fdata-sections -fno-common -fmessage-length=0)
add_compile_options($<$<COMPILE_LANGUAGE:ASM>:-x$<SEMICOLON>assembler-with-cpp>)
add_definitions(-DDEBUG -DUSE_HAL_DRIVER -DAT32F403ARGT7 -DSTM32F405xx -DARM_MATH_CM4)

elseif(DEFINED RISCV)

set(CMAKE_C_COMPILER riscv-none-embed-gcc)
set(CMAKE_CXX_COMPILER riscv-none-embed-g++)
set(CMAKE_ASM_COMPILER riscv-none-embed-gcc)
set(CMAKE_AR riscv-none-embed-ar)
set(CMAKE_OBJCOPY riscv-none-embed-objcopy)
set(CMAKE_OBJDUMP riscv-none-embed-objdump)
set(SIZE riscv-none-embed-size)
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)

add_compile_options(-march=rv32imafcxw -mabi=ilp32f -msmall-data-limit=8 -mno-save-restore -fmessage-length=0)
add_compile_options(-fsigned-char -ffunction-sections -fdata-sections -Wunused -Wuninitialized)
add_compile_options($<$<COMPILE_LANGUAGE:ASM>:-x$<SEMICOLON>assembler-with-cpp>)

add_definitions()

endif()

project(BHAL C CXX ASM)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_C_STANDARD 11)

# add_subdirectory(ch32bootloader)

include_directories(    User)
file(GLOB SOURCES       "User/*.cpp" "User/*.c")

if(DEFINED AT32)
include_directories(    AT32 AT32/drivers/inc AT32/cmsis/cm4/core_support AT32/cmsis/cm4/device_support
                        AT32/middlewares/freertos/source/include AT32/middlewares/freertos/source/portable/GCC/ARM_CM4F 
                        AT32/middlewares/usbd_drivers/inc AT32/middlewares/usbd_class/custom_hid)
file(GLOB SOURCES       ${SOURCES} "AT32/*.*" "AT32/drivers/src/*.c" "AT32/cmsis/cm4/device_support/*.c" "AT32/middlewares/freertos/source/portable/GCC/ARM_CM4F/*.c"
                        "AT32/middlewares/freertos/source/portable/memmang/heap_4.c" "AT32/middlewares/freertos/source/*.c" "AT32/middlewares/usbd_drivers/src/*.c"
                        "AT32/middlewares/usbd_class/custom_hid/*.c")

elseif(DEFINED STM32)
include_directories(    STM32 STM32/Core/Inc STM32/Drivers/CMSIS/DSP/Include STM32/USB_DEVICE/App STM32/USB_DEVICE/Target STM32/Drivers/STM32F4xx_HAL_Driver/Inc 
                        STM32/Drivers/STM32F4xx_HAL_Driver/Inc/Legacy STM32/Middlewares/Third_Party/FreeRTOS/Source/include STM32/Drivers/CMSIS/Include
                        STM32/Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM4F STM32/Middlewares/ST/STM32_USB_Device_Library/Core/Inc 
                        STM32/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc STM32/Middlewares/ST/STM32_USB_Device_Library/Class/CustomHID/Inc 
                        STM32/Drivers/CMSIS/Device/ST/STM32F4xx/Include STM32/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2 )
file(GLOB_RECURSE SOURCES ${SOURCES} "STM32/Core/*.*" "STM32/Middlewares/ST/STM32_USB_Device_Library/*.*" "STM32/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/*.*" 
                                     "STM32/Drivers/STM32F4xx_HAL_Driver/*.*" "STM32/USB_DEVICE/*.*")
file(GLOB SOURCES       ${SOURCES} "STM32/Middlewares/Third_Party/FreeRTOS/Source/*.c" "STM32/Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM4F/*.c"
                        "STM32/Middlewares/Third_Party/FreeRTOS/Source/portable/MemMang/heap_4.c" "STM32/*.*")
else()
include_directories(    CH32 CH32/Core CH32/Debug CH32/Peripheral/inc CH32/FreeRTOS/include CH32/FreeRTOS/portable/GCC/RISC-V
                        CH32/FreeRTOS/portable/GCC/RISC-V/chip_specific_extensions/RV32I_PFIC_no_extensions)
file(GLOB SOURCES       ${SOURCES} "CH32/*.*" "CH32/Core/*.c" "CH32/Debug/*.c" "CH32/Peripheral/src/*.c" "CH32/FreeRTOS/*.c" "CH32/FreeRTOS/portable/GCC/RISC-V/*.*"
                        "CH32/FreeRTOS/portable/MemMang/*.c")
endif()

# set(SOURECES_TEMP "main.cpp" "GPIO.cpp" "BHAL.cpp")


if(DEFINED ARM)
add_link_options(-Wl,-gc-sections,--print-memory-usage,-Map=${PROJECT_BINARY_DIR}/${PROJECT_NAME}.map)
add_link_options(-mcpu=cortex-m4 -mthumb -u_printf_float)
# add_link_options(--specs=nano.specs --specs=nosys.specs)

if(DEFINED AT32)
set(LINKER_SCRIPT ${CMAKE_SOURCE_DIR}/AT32/AT32F403AxG_FLASH.ld)
add_link_options(-T ${LINKER_SCRIPT})
set(ASM_S "AT32/startup_at32f403a_407.s")

elseif(DEFINED STM32)
set(LINKER_SCRIPT ${CMAKE_SOURCE_DIR}/STM32/STM32F405RGTX_FLASH.ld)
add_link_options(-T ${LINKER_SCRIPT})
endif()

elseif(DEFINED RISCV)
set(LINKER_SCRIPT ${CMAKE_SOURCE_DIR}/CH32/Link.ld)
link_libraries(libm.a)
add_link_options(-march=rv32imafcxw -mabi=ilp32f -msmall-data-limit=8 -mno-save-restore -fmessage-length=0 -fsigned-char)
add_link_options(-ffunction-sections -fdata-sections -Wunused -Wuninitialized -T ${LINKER_SCRIPT})
add_link_options(-nostartfiles -Xlinker --gc-sections -Wl,--print-memory-usage,-Map=${PROJECT_BINARY_DIR}/${PROJECT_NAME}.map --specs=nano.specs -lm -u _printf_float -lprintfloat -o)

set(ASM_S "CH32/startup_ch32v30x_D8C.S")
endif()

#设定可执行二进制文件的目录
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/OUT)
set(LIBRARY_OUTPUT_PATH  ${PROJECT_SOURCE_DIR}/OUT/Lib)

link_directories( ${PROJECT_SOURCE_DIR}/OUT/Lib)
# link_libraries(libENC.a)
# add_library(ENC STATIC User/ENC.cpp)
add_executable(${PROJECT_NAME}.elf ${SOURCES} ${SOURECES_TEMP} ${ASM_S} ${LINKER_SCRIPT})
# 编译静态库
# add_library(库名称 STATIC 代码文件名称) 

# 编译动态库
# add_library(库名称 SHARED 代码文件名称) 

set(HEX_FILE ${PROJECT_SOURCE_DIR}/OUT/${PROJECT_NAME}.hex)
set(BIN_FILE ${PROJECT_SOURCE_DIR}/OUT/${PROJECT_NAME}.bin)

# message(STATUS "Enter cmake ${CMAKE_CURRENT_LIST_DIR}")
# message(WARNING "Enter cmake ${CMAKE_CURRENT_LIST_DIR}")
# message(FATAL_ERROR  "Enter cmake ${CMAKE_CURRENT_LIST_DIR}")

add_custom_command(TARGET ${PROJECT_NAME}.elf POST_BUILD
        COMMAND ${CMAKE_OBJCOPY} -Oihex $<TARGET_FILE:${PROJECT_NAME}.elf> ${HEX_FILE}
        COMMAND ${CMAKE_OBJCOPY} -Obinary $<TARGET_FILE:${PROJECT_NAME}.elf> ${BIN_FILE}
        COMMENT "Building ${HEX_FILE}
Building ${BIN_FILE}")
